#pragma once

#include <iostream>
#include <string>
#include <functional>
#include "Sock.hpp"

static const uint16_t defaultport = 8888;

using func_t = std::function<std::string(std::string &)>; // 定义一个对象返回值是string，参数也是string

class HttpServer; // 先声明

class ThreadData
{
public:
    ThreadData(int sock, std::string &ip, uint16_t &port, HttpServer *hsvr)
        : _sock(sock), _ip(ip), _port(port), _hsvr(hsvr)
    {
    }
    ~ThreadData()
    {
    }

public:
    int _sock;
    std::string _ip;
    uint16_t _port;
    HttpServer *_hsvr;
};

class HttpServer
{
public:
    HttpServer(func_t function, uint16_t port = defaultport)
        : _func(function), _port(port)
    {
    }

    void InitServer()
    {
        _listensock.Socket();
        _listensock.Bind(_port);
        _listensock.Listen();
    }

    void Start()
    {
        while (true)
        {
            std::string clientip;
            uint16_t clientport;
            int sock = _listensock.Accept(&clientip, &clientport);
            if (sock < 0)
                continue;

            pthread_t tid;
            ThreadData *td = new ThreadData(sock, clientip, clientport, this);
            pthread_create(&tid, nullptr, threadRoutine, td);
        }
    }

    static void *threadRoutine(void *args)
    {
        pthread_detach(pthread_self());
        ThreadData *td = static_cast<ThreadData *>(args);
        td->_hsvr->HandleHttpRequest(td->_sock);
        close(td->_sock);//响应结束关闭套接字
        delete td;
    }

    void HandleHttpRequest(int sock)
    {
        char buffer[4096];
        ssize_t s = recv(sock, buffer, sizeof(buffer) - 1, 0);
        std::string request;
        if (s > 0)
        {
            buffer[s] = 0; // 最后置\0
            request = buffer;
            std::string response = _func(request);            // 获取响应
            send(sock, response.c_str(), response.size(), 0); // 返回响应
        }
        else
        {
            logMessage(Info, "client quit……");
        }
    }

    ~HttpServer()
    {
    }

private:
    int _port;
    Sock _listensock;
    func_t _func;
};